package com.yupi.shanoj.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.shanoj.common.BaseResponse;
import com.yupi.shanoj.common.ErrorCode;
import com.yupi.shanoj.common.ResultUtils;
import com.yupi.shanoj.mapper.VideoMapper;
import com.yupi.shanoj.model.dto.video.VideoAddRequest;
import com.yupi.shanoj.model.entity.User;
import com.yupi.shanoj.model.entity.Video;
import com.yupi.shanoj.service.UserService;
import com.yupi.shanoj.service.VideoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
* @author 23949
* @description 针对表【video(视频信息表)】的数据库操作Service实现
* @createDate 2024-07-17 14:26:00
*/
@Slf4j
@Service
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video>
    implements VideoService{

    @Value("D:/uploadfile/public/img/cover")
    private String COVER_DIRECTORY;

    @Value("D:/uploadfile/public/video")
    private String VIDEO_DIRECTORY;

    @Value("D:/uploadfile/public/chunk")
    private String CHUNK_DIRECTORY;

    @Autowired
    private UserService userService;

    @Autowired
    private VideoMapper videoMapper;

    @Autowired
    @Qualifier("taskExecutor")
    private Executor taskExecutor;

    @Override
    public BaseResponse<Long> askChunk(String hash) {
        return null;
    }

    @Override
    public BaseResponse<Long> uploadChunk(MultipartFile chunk, String hash, Integer index) throws IOException {
        //构建分片文件名
        String chunkFileName=hash+"-"+index;
        //存储到本地
        //构建分片文件的完整路径
        String chunkFilePath= Paths.get(CHUNK_DIRECTORY,chunkFileName).toString();
        File chunkFile=new File(chunkFilePath);
        if(chunkFile.exists()){
            log.warn("分片"+chunkFilePath+"已经存在");
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"分片已经存在");
        }
        chunk.transferTo(chunkFile);
        return ResultUtils.success(chunkFile.length());
    }

    @Override
    public BaseResponse<Long> cancelUpload(String hash) {
        //删除本地分片文件
        //获取本地分片文件目录
        File chunkDir=new File(CHUNK_DIRECTORY);
        File[] chunkFiles=chunkDir.listFiles((dir,name)->name.startsWith(hash+"-"));
        log.info("当前要删除的文件数量"+chunkFiles.length);
        if(chunkFiles!=null&&chunkFiles.length>0){
            for(File chunkFile:chunkFiles){
                chunkFile.delete();
            }
        }
        System.out.println("删除分片成功");
        return ResultUtils.success(0L);
    }

    @Override
    public BaseResponse<Long> addVideo(VideoAddRequest videoAddRequest, MultipartFile cover) {
        Integer userId = videoAddRequest.getUserId();
        if(videoAddRequest.getTitle().trim().length()==0){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"标题不能为空");
        }
        if(videoAddRequest.getTitle().length()>80){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"标题不能超过80个字符");
        }
        if(videoAddRequest.getDescr().length()>200){
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"描述不能超过200个字符");
        }
        try{
            long timestamp = System.currentTimeMillis();
            String fileName=timestamp+videoAddRequest.getVideoHash()+".jpg";
            String path=Paths.get(COVER_DIRECTORY,fileName).toString();
            File file = new File(path);
            log.info("封面的绝对路径"+file.getAbsolutePath());
            cover.transferTo(file);
            videoAddRequest.setCoverUrl(file.getAbsolutePath());
        }catch (IOException e){
            log.error("封面上传失败");
            return ResultUtils.error(ErrorCode.PARAMS_ERROR,"封面上传失败");
        }

        CompletableFuture.runAsync(()->{
            try{
                mergeChunks(videoAddRequest);
            }catch (IOException e){
                log.error("合并分片失败");
                e.printStackTrace();
            }
        },taskExecutor);

        return null;
    }

    @Transactional
    public void mergeChunks(VideoAddRequest videoAddRequest) throws IOException {
        String url = null;

        //合并到本地
        //获取分片文件的存储目录
        File chunkDir=new File(CHUNK_DIRECTORY);
        //获取当前时间戳
        long timestamp = System.currentTimeMillis();
        //构建文件名将时间戳，假如文件开头
        String filename=timestamp+videoAddRequest.getVideoHash()+".mp4";
        //构建完整的文件路径
        String FilePath=Paths.get(VIDEO_DIRECTORY,filename).toString();
        //创建文件
        File finalfile=new File(FilePath);
        //获取所有的对应分片文件
        File[] chunkFiles=chunkDir.listFiles((dir,name)->name.startsWith(videoAddRequest.getVideoHash()+"-"));
        if(chunkFiles!=null&& chunkFiles.length>0){
            List<File> sortedChunkFiles= Arrays.stream(chunkFiles)
                    .sorted(Comparator.comparingInt(file->Integer.parseInt(file.getName().split("-")[1])))
                    .collect(Collectors.toList());
            try{
                log.info("正在合并视频");
                for(File chunkFile:sortedChunkFiles){
                    byte[] chunkBytes= FileUtils.readFileToByteArray(chunkFile);
                    FileUtils.writeByteArrayToFile(finalfile,chunkBytes,true);
                    chunkFile.delete();
                }
                log.info("合并完成");
                url=finalfile.getAbsolutePath();
            }catch (IOException e){
                log.error("合并视频失败");
                e.printStackTrace();
            }
        }else{
            log.error("没有找到分片文件");
            return;
        }
        Video video=new Video();
        video.setAuth(videoAddRequest.getAuth());
        video.setCoverUrl(videoAddRequest.getCoverUrl());
        video.setDescr(videoAddRequest.getDescr());
        video.setDuration(videoAddRequest.getDuration());
        video.setMcId(videoAddRequest.getMcId());
        video.setScId(videoAddRequest.getScId());
        video.setStatus(videoAddRequest.getStatus());
        video.setTags(videoAddRequest.getTags());
        video.setTitle(videoAddRequest.getTitle());
        video.setType(videoAddRequest.getType());
        video.setUploadDate(new Date());
        video.setUserId(videoAddRequest.getUserId());
        video.setVideoUrl(url);
        int insert = videoMapper.insert(video);
        if(insert<=0){
            log.error("插入视频失败");
            return;
        }else{
            log.info("插入视频成功");
        }

    }

}




